﻿using System;
using System.Data;
using System.Collections.Generic;

namespace BusinessLayer
{
    public struct A
    {
        public double x;
        public double y;
        public A(double i, double j)
        {
            x = i;
            y = j;
        }
    }
    /// <summary>
    /// The car.
    /// </summary>
    public class Car : BusinessEntity
    {
        /// <summary>
        /// The car repository.
        /// </summary>
        public class CarRepository : Repository<Car>
        {


            public List<CarDriver> GetDrivers(int carId)
            {
                List<CarDriver> drivers = new List<CarDriver>();
                DataAccessLayer.Reader reader = (DataAccessLayer.Reader)DataAccessLayer.DAL.Operation("Read", "Driver", new Dictionary<string, object> { { "Id", carId } });
                while (reader.Read())
                {
                    drivers.Add(new CarDriver((DateTime)reader.Current["From"], (DateTime)reader.Current["To"], Driver.Repository.ReadById((int)reader.Current["DriverId"])));
                }
                return drivers;
            }

            public void SetDriver(int carId, int driverId, DateTime from, DateTime to)
            {
                DataAccessLayer.DAL.Operation("Write", "Driver", new Dictionary<string, object> { { "CarId", carId }, { "DriverId", driverId }, { "From", from }, { "To", to } });
            }

            public void RemoveDriversBefore(int carId, DateTime time)
            {
                DataAccessLayer.DAL.Operation("Remove", "Driver", new Dictionary<string, object> { { "CarId", carId }, { "Time", time } });
            }
        }

        /// <summary>
        /// The car reposytory.
        /// </summary>
        public static CarRepository Repository = new CarRepository();

        /// <summary>
        /// Gets or sets the name.
        /// </summary>
        public string Name
        {
            get { return (string)this.Get("Name"); }
            set { this.Set("Name", value); }
        }

        /// <summary>
        /// Gets the id.
        /// </summary>
        public int Id
        {
            get { return (int)this.Get("Id"); }
        }


        /// <summary>
        /// Gets or sets the car number.
        /// </summary>
        public string CarNumber
        {
            get { return (string)this.Get("CarNumber"); }
            set { this.Set("CarNumber", value); }
        }


        /// <summary>
        /// Gets or sets a value indicating whether enabled.
        /// </summary>
        public bool Enabled
        {
            get { return (bool)this.Get("Enabled"); }
            set { this.Set("Enabled", value); }
        }


        /// <summary>
        /// Initializes a new instance of the <see cref="Car"/> class.
        /// </summary>
        internal Car(Dictionary<string, object> car)
        {
            this.Initialize(car);
        }

        /// <summary>
        /// Default constructor.
        /// Must call Initialize method before using.
        /// </summary>
        public Car()
        {
        }

        /// <summary>
        /// Save the car.
        /// </summary>
        public override void Save()
        {
            Car.Repository.Write(this);
        }

        /// <summary>
        /// The current state.
        /// </summary>
        public CarState CurrentState()
        {
            CarState last;
            Reader<CarState> reader = CarState.Repository.ReadAll(this.Id);
            if (reader.Read())
                last = reader.Current;
            else
                throw new Exception("No info about car");

            while (reader.Read())
                if (reader.Current.Time > last.Time)
                    last = reader.Current;
            reader.Close();

            return last;
        }

        public Driver CurrentDriver()
        {
            List<CarDriver> drivers = Car.Repository.GetDrivers(this.Id);
            CarDriver driver;
            if (drivers.Count > 0)
                driver = drivers[0];
            else
                throw new Exception("No drivers");
            for (int i = 0; i < drivers.Count; i++)
                if (driver.To < drivers[i].To)
                    driver = drivers[i];

            return driver.Driver;
        }

        /// <summary>
        /// Is in park.
        /// </summary>
        public bool IsInPark()
        {
            Reader<Park> reader = Park.Repository.ReadAll();
            while(reader.Read())
            {
                if (reader.Current.CarInPark(this))
                    return true;
            }
            reader.Close();

            return false;
        }

        /// <summary>
        /// Remove states of this car before time specified.
        /// </summary>
        public void RemoveStates(DateTime time)
        {
            CarState.Repository.Remove(this.Id, time);
        }

        /// <summary>
        /// Remove all states of this car.
        /// </summary>
        public void RemoveAllStates()
        {
            CarState.Repository.Remove(this.Id);
        }


    }
}
